package com.sqlcheck.service.impl;

import com.sqlcheck.dto.request.ManualSqlAnalysisRequest;
import com.sqlcheck.dto.request.UnifiedAnalysisRequest;
import com.sqlcheck.dto.response.ManualSqlAnalysisResponse;
import com.sqlcheck.dto.response.UnifiedAnalysisResponse;
import com.sqlcheck.entity.ManualSqlAnalysis;
import com.sqlcheck.entity.ScanResult;
import com.sqlcheck.service.ManualSqlAnalysisService;
import com.sqlcheck.service.UnifiedAnalysisService;
import com.sqlcheck.repository.ManualSqlAnalysisRepository;
import com.sqlcheck.repository.ScanTaskRepository;
import com.sqlcheck.util.JsonUtils;
import com.sqlcheck.enums.TaskType;
import com.sqlcheck.entity.ScanTask;
import com.sqlcheck.enums.TaskStatus;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class ManualSqlAnalysisServiceImpl implements ManualSqlAnalysisService {

    private final UnifiedAnalysisService unifiedAnalysisService;
    private final ManualSqlAnalysisRepository repository;
    private final ScanTaskRepository scanTaskRepository;

    @Override
    public ManualSqlAnalysisResponse analyzeSql(ManualSqlAnalysisRequest request) {
        try {
            log.info("开始统一手动SQL分析, 源数据库类型: {}, 目标数据库类型: {}, 分析引擎: {}",
                    request.getSourceDbType(), request.getTargetDbType(), request.getAnalysisEngine());

            // 构建统一分析请求（与扫描任务使用相同的请求格式）
            UnifiedAnalysisRequest unifiedRequest = buildUnifiedAnalysisRequest(request);

            // 使用统一的分层分析服务
            UnifiedAnalysisResponse unifiedResponse = unifiedAnalysisService.performLayeredAnalysis(unifiedRequest);

            if (!unifiedResponse.isSuccess()) {
                return ManualSqlAnalysisResponse.builder()
                        .success(false)
                        .errorMessage(unifiedResponse.getErrorMessage())
                        .analysisTime(LocalDateTime.now())
                        .build();
            }

            // 转换为ManualSqlAnalysisResponse格式（保持API兼容性）
            return convertToManualResponse(unifiedResponse, request);

        } catch (Exception e) {
            log.error("统一手动SQL分析失败", e);
            return ManualSqlAnalysisResponse.builder()
                    .success(false)
                    .errorMessage("分析过程中发生错误: " + e.getMessage())
                    .analysisTime(LocalDateTime.now())
                    .build();
        }
    }

    /**
     * 构建统一分析请求
     */
    private UnifiedAnalysisRequest buildUnifiedAnalysisRequest(ManualSqlAnalysisRequest request) {
        // 根据请求参数确定是否启用AI增强
        boolean aiEnhancementEnabled = determineAIEnhancement(request.getAnalysisEngine());

        return UnifiedAnalysisRequest.builder()
                .sqlContent(request.getSqlContent())
                .sourceDbType(request.getSourceDbType())
                .targetDbType(request.getTargetDbType())
                .aiEnhancementEnabled(aiEnhancementEnabled)
                .taskName(request.getTaskName() != null ? request.getTaskName()
                        : "Manual-Analysis-" + System.currentTimeMillis())
                .userId(getCurrentUserId()) // 从上下文获取用户ID
                .build();
    }

    /**
     * 确定是否启用AI增强
     */
    private boolean determineAIEnhancement(String engineType) {
        if (engineType == null) {
            return false;
        }

        switch (engineType.toUpperCase()) {
            case "LLM_BASED":
            case "HYBRID":
                return true;
            case "RULE_BASED":
            default:
                return false;
        }
    }

    /**
     * 转换统一分析结果为手动分析响应格式（保持向后兼容）
     */
    private ManualSqlAnalysisResponse convertToManualResponse(
            UnifiedAnalysisResponse unified, ManualSqlAnalysisRequest original) {

        return ManualSqlAnalysisResponse.builder()
                .success(true)
                .sqlStatements(unified.getSqlStatements()) // 使用统一解析的结果
                .issues(unified.getIssues()) // 直接使用ScanResult列表
                .totalIssues(unified.getStatistics() != null ? unified.getStatistics().getTotalIssues()
                        : unified.getIssues().size())
                .highSeverityCount(unified.getStatistics() != null ? unified.getStatistics().getHighSeverityCount() : 0)
                .mediumSeverityCount(
                        unified.getStatistics() != null ? unified.getStatistics().getMediumSeverityCount() : 0)
                .lowSeverityCount(unified.getStatistics() != null ? unified.getStatistics().getLowSeverityCount() : 0)
                .analysisTime(unified.getAnalysisTime() != null ? unified.getAnalysisTime() : LocalDateTime.now())
                .build();
    }


    /**
     * 获取当前用户ID（从上下文获取，这里使用默认值）
     */
    private Long getCurrentUserId() {
        // TODO: 从安全上下文或请求头中获取当前用户ID
        return 1L; // 临时使用默认值
    }

    @Override
    @Transactional
    public Long saveAnalysisTask(ManualSqlAnalysisRequest request) {
        try {
            // 先执行分析（使用统一分析服务）
            ManualSqlAnalysisResponse analysisResult = analyzeSql(request);

            // 1. 创建扫描任务
            ScanTask task = ScanTask.builder()
                    .taskName(request.getTaskName() != null ? request.getTaskName() : "手动SQL分析_" + LocalDateTime.now())
                    .taskType(TaskType.MANUAL_SQL)
                    .status(analysisResult.isSuccess() ? TaskStatus.SUCCESS : TaskStatus.FAILED)
                    .description("手动SQL兼容性分析")
                    .userId(getCurrentUserId())
                    .startTime(LocalDateTime.now())
                    .endTime(LocalDateTime.now())
                    .build();

            if (!analysisResult.isSuccess()) {
                task.setErrorMessage(analysisResult.getErrorMessage());
            }

            // 设置配置信息
            Map<String, Object> config = new HashMap<>();
            config.put("sourceDbType", request.getSourceDbType().name());
            config.put("targetDbType", request.getTargetDbType().name());
            config.put("sqlContent", request.getSqlContent());
            config.put("analysisEngine", request.getAnalysisEngine()); // 记录使用的分析引擎
            task.setConfig(config);

            ScanTask savedTask = scanTaskRepository.insert(task) > 0 ? task : null;
            if (savedTask == null) {
                throw new RuntimeException("保存扫描任务失败");
            }
            log.info("保存扫描任务成功, ID: {}, 分析引擎: {}", savedTask.getId(), request.getAnalysisEngine());

            // 2. 创建手动SQL分析记录
            ManualSqlAnalysis analysis = ManualSqlAnalysis.builder()
                    .taskId(savedTask.getId())
                    .sqlContent(request.getSqlContent())
                    .sourceDbType(request.getSourceDbType())
                    .targetDbType(request.getTargetDbType())
                    .analysisResultJson(JsonUtils.objectToJson(analysisResult))
                    .compatibilityLevel(determineCompatibilityLevel(analysisResult))
                    .createdAt(LocalDateTime.now())
                    .updatedAt(LocalDateTime.now())
                    .build();

            ManualSqlAnalysis savedAnalysis = repository.insert(analysis) > 0 ? analysis : null;
            if (savedAnalysis == null) {
                throw new RuntimeException("保存手动SQL分析记录失败");
            }
            log.info("保存手动SQL分析记录成功, ID: {}", savedAnalysis.getId());

            return savedTask.getId();

        } catch (Exception e) {
            log.error("保存手动SQL分析任务失败", e);
            throw new RuntimeException("保存分析任务失败: " + e.getMessage());
        }
    }

    @Override
    public ManualSqlAnalysis getAnalysisTask(Long id) {
        return repository.selectById(id);
    }

    private ManualSqlAnalysis.CompatibilityLevel determineCompatibilityLevel(ManualSqlAnalysisResponse analysisResult) {
        if (!analysisResult.isSuccess() || analysisResult.getHighSeverityCount() > 0) {
            return ManualSqlAnalysis.CompatibilityLevel.INCOMPATIBLE;
        } else if (analysisResult.getMediumSeverityCount() > 0) {
            return ManualSqlAnalysis.CompatibilityLevel.MEDIUM;
        } else if (analysisResult.getLowSeverityCount() > 0) {
            return ManualSqlAnalysis.CompatibilityLevel.LOW;
        } else {
            return ManualSqlAnalysis.CompatibilityLevel.HIGH;
        }
    }
}